package com.yhb.channel.impl.YPL;

import com.alibaba.fastjson.JSONObject;
import com.yhb.channel.ChannelFactory;
import com.yhb.channel.FlowService;
import com.yhb.channel.PayChannel;
import com.yhb.channel.exception.TryingBindCardException;
import com.yhb.channel.impl.YPL.http.Request.BindCardRequest;
import com.yhb.channel.impl.YPL.http.Response.BindCardResponse;
import com.yhb.channel.impl.YPL.http.YPLHTTPClient;
import com.yhb.channel.model.IBankCard;
import com.yhb.channel.model.IUserIdentify;
import com.yhb.channel.model.IUserInfo;
import com.yhb.channel.model.TryPayPayload;
import com.yhb.channel.provider.*;
import com.yhb.channel.utils.*;
import com.yhb.channel.utils.encryptAndSign.ChannelPrivateKeyUtils;
import com.yhb.channel.utils.encryptAndSign.YPLRSAUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import sdk.inlet.InletHelper;
import sdk.inlet.domain.*;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class YPLChannel implements PayChannel {
    // 配置
    private ConfigGetter configGetter;
    private String merchantId;
    @Value("${config.url}")
    private String baseUrl;

    // 常量
    public static final String CHANNEL_NAME = "易票联";
    private static final String CHANNEL_TYPE = ChannelFactory.YPL;
    private static final String YPL_REDIS_BINDCARD_SMS_PREFIX = "YPL-BindcardSMS-UserId-";
    private static ChannelLogger logger;
    private static final YPLRSAUtils rsa = new YPLRSAUtils();
    private static String privateKey;
    private static String publicKey;

    /* ------------Base Provider Beans or utils------------ */
    @Autowired
    private ChannelBaseService channelBaseService;

    @Autowired
    private YPLHTTPClient yplhttpClient;

    @Autowired
    private YPLConfig yplConfig;

    /* 启动方法 */
    @PostConstruct
    private void init() {
        configGetter = new ConfigGetter(CHANNEL_TYPE, channelBaseService.iUtilProvider);
        logger = new ChannelLogger(CHANNEL_NAME, YPLException.class, channelBaseService.iUtilProvider);
        try {
            privateKey = new ChannelPrivateKeyUtils(
                    yplConfig.getPrivateKeyFile(), yplConfig.getPrivateKeyPassword()).getPrivateKeyString();
        } catch (UnrecoverableKeyException | NoSuchAlgorithmException | KeyStoreException | IOException | CertificateException e) {
            e.printStackTrace();
        }
        publicKey = YPLRSAUtils.getKeyFromKeyPath(yplConfig.getPublicKeyPath());
    }

    /* 业务方法 */
    private static String getAreaCode(String province, String city, String region) {
        return YPLAreaConstant.getAreaCode(province, city, region);
    }

//    @Override
//    public void userSignUp(String userId, String province, String city, IBankCard card, String payRate) {
//        IUserInfo iUserInfo = channelBaseService.iUserInfoProvider.getUserInfo(userId);
//        IUserIdentify iUserIdentify = channelBaseService.iUserIdentifyProvider.getUserIdentify(userId);
//        String userName = iUserIdentify.getUserName();
//        String smallMerchant = "50"; // 商户类别 50：小微商户
//        String idCardType = "0"; // 身份证
//        String settMode = "D0"; // 结算周期类型
//        String settCircle = "0"; // 结算周期
//        String bankAccountType = "2"; // 结算账户类型 2是对私
//        String SPLITTED = "SPLITTED"; // 被分账业务
//        String WITHDRAW_CREDIT_CARD = "WITHDRAW_CREDIT_CARD"; // 提现到信用卡
//        String businessEndDate = "20991231"; // 业务过期时间
//        String businessRatioMode = "2"; // 费率计算模式：按比例
//        String businessRatioParam = "0"; // 文档：无卡业务这里一般填 0，这 里是指易票联收取分账子商户的费用
//        String email = "";
//        String qq = "";
//        String rawValidation = iUserIdentify.getValidation();
//        String areaCode = getAreaCode(card.getProvince(), card.getCity(), card.getDistrict());
//        String notifyUrl = baseUrl + "channel/callback/" + CHANNEL_TYPE + "/" + YPLConstant.CALLBACK_PAY;
//        if ("".equals(areaCode)) {
//            throw new YPLException(YPLConstant.ERROR_PARAMETER_WRONG, "获取地区code失败");
//        }
//        int contactType = 1; // 联系人类型为管理员

//        InletMerchantRequest imr = new InletMerchantRequest();
//
//        imr.setName(userName);
//        imr.setShortName(userName);
//        imr.setLealPersonName(userName);
//        imr.setLealPersonIdentificationType(idCardType);
//        imr.setLealPersonIdentificationNo(iUserIdentify.getIdCardNum());//身份证
//        imr.setMobile(iUserInfo.getUserPhone());
//        imr.setLealPersonIdentificationExpiredDate(
//                ChannelStringUtils.getEndOfValidation(rawValidation, "yyyy-MM-dd")); // 身份证有效期截止日期
//
//        imr.setType(smallMerchant);
//        imr.setAreaCode(areaCode); //归属省市区
//        imr.setSettMode(settMode);
//        imr.setSettCircle(settCircle);
//        imr.setBankAccountType(bankAccountType);
//
//        imr.setCustomerNameInBank(userName); // 银行持卡人姓名
//        imr.setAccountNo(card.getNumber()); // 银行账号/卡号 非必填
//        imr.setSettTarget("2");             // 结算目标,必填 2：结算到易票联账户
//        imr.setNotifyURL(); // 异步通知URL,必填
//
//        List<Business> businessList = new ArrayList<>();
//        businessList.add(new Business(SPLITTED, ChannelDateUtil.getCurrentDateString(),
//                        businessEndDate,  businessRatioMode,  businessRatioParam));
//        businessList.add(new Business( WITHDRAW_CREDIT_CARD, ChannelDateUtil.getCurrentDateString(),
//                        businessEndDate,  businessRatioMode,  businessRatioParam));
//        imr.setBusinessList(businessList);  // 开通的业务列表必填
//
//        List<Contact> contactList = new ArrayList<>();
//        contactList.add(new Contact(contactType,  imr.getName(),  imr.getMobile(),  email,  qq));
//        imr.setContactList(contactList);    // 联系人信息列表必填
//
//        InletMerchantResponse response = null;
//        try {
//            response = InletHelper.addMerchant(imr);
//        } catch (Exception e) {
//            throw new YPLException(YPLConstant.ERROR_DEFAULT_CODE, "签约请求错误", e);
//        }
//        String resultJson = JSONObject.toJSONString(response);
//    }

    @Override
    public void updatePayRate(String userId, String payRate) {

    }

    @Override
    public String bindCard(String userId, IBankCard card, String clientIP) {
        IUserInfo iUserInfo = channelBaseService.iUserInfoProvider.getUserInfo(userId);
        IUserIdentify iUserIdentify = channelBaseService.iUserIdentifyProvider.getUserIdentify(userId);

        String customerCode = yplConfig.getCustomerCode();
        String mchtOrderNo = UUID.randomUUID().toString();
        String memberId = customerCode;
        String userName = rsa.encryptByPublicKey(iUserIdentify.getUserName(), publicKey);
        String phoneNum = rsa.encryptByPublicKey(card.getPhoneNumber(), publicKey);
        String bankCardNo = rsa.encryptByPublicKey(card.getNumber(), publicKey);
        BindCardRequest.CardType bankCardType = card.getCardType() == 1 ?
                BindCardRequest.CardType.credit : BindCardRequest.CardType.debit;
        String certificatesNo = rsa.encryptByPublicKey(iUserIdentify.getIdCardNum(), publicKey);
        String nonceStr = UUID.randomUUID().toString();

        BindCardRequest bindCardRequest = BindCardRequest.builder()
                .customerCode(customerCode)
                .mchtOrderNo(mchtOrderNo)
                .memberId(memberId)
                .userName(userName)
                .phoneNum(phoneNum)
                .bankCardNo(bankCardNo)
                .bankCardType(bankCardType)
                .certificatesNo(certificatesNo)
                .version("2.0")
                .certificatesType("01")
                .isSendIssuer(true)
                .build();
        bindCardRequest.setNonceStr(nonceStr);

        if (BindCardRequest.CardType.credit.equals(bankCardType)) {
            String cvn = rsa.encryptByPublicKey(card.getCvv2(), publicKey);
            String validation = card.getValidation(); // 拿到的是mmyy
            String expired = validation.substring(2) + validation.substring(0, 2); // 但是通道要求yymm 有毒2333
            bindCardRequest.setCvn(cvn);
            bindCardRequest.setExpired(rsa.encryptByPublicKey(expired, publicKey));
        }

        String res = yplhttpClient.http("bindCard", bindCardRequest, yplConfig.getBindCardUrl());
        BindCardResponse bindCardResponse = ChannelJSONUtil.parseJson(res, BindCardResponse.class);
        if (bindCardResponse.isSuccess()) {
            logger.info("bindCard 调用成功");
            logger.info(res);
        }
        return null;
    }

//    @Override
//    public String tryBindCard(String userId, IBankCard card, String clientIP, String payRate) {
//        return null;
//    }

    @Override
    public String bindCardConfirm(String smsCode, String userId, String smsUUID) {
        return null;
    }

//    @Override
//    public String pay(String userId,
//                      IBankCard payCard, IBankCard remitCard,
//                      BigDecimal orderAmount, BigDecimal userFeeAmount, String clientIP) {
//        return null;
//    }

//    @Override
//    public String tryPay(String userId, IBankCard payCard, IBankCard remitCard, BigDecimal orderAmount, BigDecimal userFeeAmount, String clientIP, String payRate) throws TryingBindCardException {
//        return null;
//    }

    @Override
    public String verifyPay(String userId, String smsCode, TryPayPayload payload) {
        return null;
    }

//    @Override
//    public String remit(String userId, IBankCard card, BigDecimal amount, BigDecimal userFeeAmount) {
//        return null;
//    }

    @Override
    public String retryRemit(String flowId, Date date) {
        return null;
    }

//    @Override
//    public boolean checkIfBound(@NotNull IBankCard card) {
//        return false;
//    }


    @Override
    public void handleCallback(String callBackAction, HttpServletRequest request, HttpServletResponse response, String orderCreateTimestamp, String info) {

    }

    public static void main(String[] args) {
        System.out.println("begin");
        System.out.println(getAreaCode("广东省", "潮州市", "潮安1区"));
        System.out.println(getAreaCode("广东省", "潮州市", "潮安区"));
        System.out.println(getAreaCode("广东省", "东莞市", "潮安区"));
        System.out.println(getAreaCode("台湾省", "东莞市", "潮安区"));
        System.out.println(getAreaCode("", "东莞市", "潮安区"));
        System.out.println(getAreaCode("北京市", "东城区", ""));
    }
}
